const puppeteer = require('puppeteer');
const { sleep } = require('../utils');

exports.BrowserTool = class BrowserTool {
	constructor(options) {
		this.username = options.username;
		this.password = options.password;
		this.host = options.host;
		this.delay = 15000; // 默认延时时间
		this.browser = null;
	}

	async init() {
		return new Promise((resolve, reject) => {
			return puppeteer.launch({
				headless: false,
				width: 1000,
				height: 1200
			}).then((browser) => {
				this.browser = browser;

				this.browser.on('disconnected', () => {
					console.log('浏览器已关闭, 终止程序');

					process.exit(1);
				});

				return browser.newPage();
			}).then(page => {
				this.rootPage = page;

				resolve();
			}).catch(e => {
				console.log(e.message);

				reject();
			});
		});
	}

	async launch() {
		try {
			await this.init();
			await this.rootPage.goto(`${this.host}/manager_house/account/login/`);

			console.log('浏览器启动成功');
		} catch (error) {
			throw new Error('浏览器启动失败');
		}
	}

	async close() {
		await this.browser.close();
	}

	// 进入登录页面
	async login() {
		const userInputBox = await this.rootPage.waitForSelector('input[name="username"]');
		const passwordInputBox = await this.rootPage.waitForSelector('input[name="password"]');

		await this.rootPage.evaluate(function (el, value) {
			el.setAttribute('value', value);
		}, userInputBox, this.username);

		await this.rootPage.evaluate(function (el, value) {
			el.setAttribute('value', value);
		}, passwordInputBox, this.password);

		const buttonElement = await this.rootPage.waitForSelector('#TANGRAM__PSP_4__submit');

		// 点击登录
		await this.rootPage.evaluate(button => button.click(), buttonElement);
		await this.rootPage.waitForNavigation(`${this.host}/manager_house/home/general/`);

		console.log('登录成功:' + this.username);
	}

	// 进入订单页面
	async gotoOrderPage() {
		const orderListButton =
			await this.rootPage.waitForSelector('a[href="/manager_house/model/order/"]');

		await this.rootPage.evaluate(button => button.click(), orderListButton);
		await this.rootPage.waitForNavigation(`${this.host}/manager_house/model/order/`);
		await sleep(3000);

		console.log('进入订单页面成功');

		return;
	}

	// 数据保存
	async saveData(data) {
		try {
			// 清除根页面的搜索框
			const searchInput = await this.rootPage.$('#search');


			await this.rootPage.evaluate(
				(el, value) => el.value = value, searchInput, data.modelId
			);

			// 点击搜索按钮
			const searchBtn = await this.rootPage.waitForSelector('#search_btn', { timeout: this.delay });

			await this.rootPage.evaluate(async el => el.click(), searchBtn);
			await this.waitSearchEventFinish(this.rootPage);
			await sleep(3000);

			// 点击编辑模型按钮
			const editmodelBtn = await this.rootPage.waitForSelector(('#data-table tbody tr:last-child td:nth-last-child(2) a[title="编辑模型"]'), {
				timeout: this.delay
			});

			await this.rootPage.evaluate(button => button.click(), editmodelBtn);

			// 打开新的标签页
			const newPageTarget = await this.browser.waitForTarget(
				target => target.opener() === this.rootPage.target()
			);

			const newPage = await newPageTarget.page();

			await sleep(5000);

			// 找到绘制户型图按钮
			const drawFloorBtn = await newPage.waitForSelector('.draw-floorplan', { timeout: this.delay });

			// 点击绘制按钮
			await newPage.evaluate(async button => {
				button.click();
			}, drawFloorBtn);

			await sleep(5000);

			const floorEditorPageTarget = await this.browser.waitForTarget(target => target.opener() === newPage.target(), { timeout: this.delay });
			const floorEditorPage = await floorEditorPageTarget.page();

			const closeBrowser = setTimeout(() => {
				console.log('页面停留超时， 关闭浏览器');

				this.browser.close();
			}, 60000);

			await floorEditorPage.setRequestInterception(true);

			const iframeElement = await floorEditorPage.waitForSelector('iframe', { timeout: this.delay });

			await sleep(10000);

			await floorEditorPage.evaluate(iframe => {
				iframe.contentWindow.postMessage(JSON.stringify({
					action: 'save_zq',
					type: 'fp',
				}), '*');
			}, iframeElement);

			await this.waitSaveEventFinish(floorEditorPage);
			await sleep(3000);
			await floorEditorPage.close();
			await newPage.close();

			clearTimeout(closeBrowser);
		} catch (error) {
			throw new Error('save data error!');
		}
	}

	async closeSubPage() {
		try {
			await this.floorEditorPage.close();
			await this.newPage.close();
		} catch (error) {
			console.log(error.message);

			return;
		}
	}

	async waitSaveEventFinish(page) {
		return new Promise((resolve) => {
			page.on('request', (request) => {
				request.continue();
			});

			page.on('response', (request) => {
				if (
					request.url()
					&& request.url().includes(`${this.host}/manager_house/model/save_data/`)
				) {
					resolve();
				}
			});
		});
	}

	async waitSearchEventFinish(page) {
		return new Promise((resolve, reject) => {
			page.on('response', async (response) => {
				if (response.url().includes('/manager_house/model/order/list/')) {
					await sleep(5000);

					await response.text();

					await sleep(3000);
					resolve();
				}
			});
		});
	}
};
